home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Personal Computer World 2009 February
/
PCWFEB09.iso
/
Software
/
Linux
/
Kubuntu 8.10
/
kubuntu-8.10-desktop-i386.iso
/
casper
/
filesystem.squashfs
/
usr
/
lib
/
udev
/
fix-persistent-net.pl
next >
Wrap
Perl Script
|
2008-10-24
|
5KB
|
186 lines
#!/usr/bin/perl
use strict;
use warnings;
my $RULES = "/etc/udev/rules.d/70-persistent-net.rules";
#-----------------------------------------------------------------------------#
# Sanity check
#-----------------------------------------------------------------------------#
die "$RULES does not exist to fix\n" unless -f $RULES;
#-----------------------------------------------------------------------------#
# Parse existing /etc/udev/rules.d/70-persistent-net.rules
#-----------------------------------------------------------------------------#
open RULES, $RULES
or die "Unable to open $RULES: $!";
my @rules;
while (<RULES>) {
# Rules may cross multiple lines when lines ends in \
while (/\\$/ && (my $extra = <RULES>)) {
$_ .= $extra;
}
# Skip lines that are empty, have only whitespace and/or comments
if (/^\s*(\#.*)?$/) {
push @rules, [ $_ ];
next;
}
# Parse rule elements
my $rule = [];
while (/(?:([\s,]*)((\S*?)\s*(==|\+=|!=|:=|=)\s*\"([^\"]*)\")|(.+))/gs) {
if (defined $1) {
push @{$rule}, $1 if length $1;
push @{$rule}, {
'text' => $2,
'key' => $3,
'op' => $4,
'val' => $5
};
} else {
push @{$rule}, $6;
}
}
push @rules, $rule;
}
close RULES
or warn "Error while closing $RULES: $!";
#-----------------------------------------------------------------------------#
# Fix rule entries
#-----------------------------------------------------------------------------#
RULE: foreach my $rule (@rules) {
my $has_rule = 0;
my $has_match = 0;
my $has_type = 0;
my $name_idx = -1;
my $name;
my $address;
MATCH: foreach my $idx (0..$#{$rule}) {
my $match = $rule->[$idx];
next unless ref $match;
$has_rule = 1;
if ($match->{key} =~ /^ATTRS?{type}$/) {
# Rule matches on interface type
$has_type = 1;
} elsif ($match->{key} =~ /^ATTRS?{address}$/) {
# Rule matches on MAC address
$has_match = 1;
$address = $match->{val};
} elsif ($match->{key} =~ /^ATTRS?{[^}]*}|ENV{[^}]*}|KERNELS$/) {
# Rule matches on a possibly unique attribute
$has_match = 1;
} elsif ($match->{key} =~ /^NAME$/ && $match->{op} =~ /^:?=$/) {
# Name setting
$name_idx = $idx;
$name = $match->{val};
}
}
next unless $has_rule;
# Comment out lines that don't match a device by any potentially unique
# property, since they'll match everything
unless ($has_match) {
unshift @{$rule}, "#removed by upgrade, will match any device\n# ";
$name_idx++;
}
# Add a match on type for any rule missing that to avoid matching
# "master" devices
unless ($has_type) {
my $type;
# Make sure that the device currently has the "1" (Ethernet) type
if (-f "/sys/class/net/$name/type"
&& `cat /sys/class/net/$name/type` =~ /^1\s*$/) {
# It does
$type = "1";
} elsif (defined $address) {
# It doesn't, it's possible that we've already renamed it to
# something else and a device exists with the right MAC address
# and a different name
opendir NET, "/sys/class/net"
or die "Unable to open /sys/class/net: $!";
my $found = 0;
while (my $dev = readdir(NET)) {
next if $dev =~ /^\./;
next unless (-f "/sys/class/net/$dev/address"
&& `cat /sys/class/net/$dev/address` =~ /^$address\s*$/i);
$found = 1;
next unless (-f "/sys/class/net/$dev/type"
&& `cat /sys/class/net/$dev/type` =~ /^1\s*$/);
# Found a device with a matching address and the right type
$type = "1";
}
closedir NET
or die "Error while closing /sys/class/net: $!";
# No device with the matching MAC address found (unplugged?)
# stick type in anyway
$type = "1" unless $found;
}
# Append a rule to match the type. If we couldn't find an Ethernet
# device with the set name, or a different name but the right address,
# then we don't attempt to change the file and instead leave a comment
# to highlight a line that might be a problem.
if (defined $type) {
my $match = {
'text' => "ATTR{type}==\"$type\"",
'key' => 'ATTR{type}',
'op' => '==',
'val' => "$type"
};
splice(@{$rule}, $name_idx, 0, $match, ", ");
$name_idx += 2;
} elsif ($has_match) {
unshift @{$rule}, "#following line may cause a device to become stuck as ${name}_rename\n#add ADDR{type}==\"...\" if that happens\n";
$name_idx++;
}
}
}
#-----------------------------------------------------------------------------#
# Write new /etc/udev/rules.d/70-persistent-net.rules
#-----------------------------------------------------------------------------#
open RULES, ">$RULES.new"
or die "Unable to open $RULES.new: $!";
foreach my $rule (@rules) {
my $line = "";
foreach my $match (@{$rule}) {
if (ref $match) {
$line .= $match->{text};
} else {
$line .= $match;
}
}
print RULES $line;
}
close RULES
or warn "Error while closing $RULES: $!";
rename "$RULES.new", $RULES
or die "Unable to replace $RULES: $!";